﻿using System;
using System.IO;
using System.Threading;
using Renci.SshNet;
using System.Text;
using System.Diagnostics;

namespace Utils
{
    public class SSH
    {
        public void CallPutty(string ip,string user,string passwd,int port)
        {
            ProcessStartInfo cmd = new ProcessStartInfo();
            cmd.FileName = Directory.GetCurrentDirectory() + "\\"+@"putty.exe";
            cmd.UseShellExecute = false;
            cmd.RedirectStandardInput = false;
            cmd.RedirectStandardOutput = true;
            cmd.Arguments = $"-ssh {user}@{ip} {port} -pw {passwd}";
            using (Process process = Process.Start(cmd))
            {
                process.WaitForExit();
            }
        }
        public bool Upload(string host, string user, string password, int port,string fileToUpload, string remotePath)
        {

            try
            {
                using (ScpClient c = new ScpClient(host, user, password))
                {
                    Debug.WriteLine("Uploading file: {0} to {1}", fileToUpload, host);
                    c.Connect();
                    c.Upload(new FileInfo(fileToUpload), remotePath);
                    c.Disconnect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        public bool ConnectByKey(string host, string user, string privateKey, int port)
        {
            System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
            var privateKeyLocation = Directory.GetCurrentDirectory() + "\\" + privateKey;
            /*
            AuthenticationMethod[] auths = new AuthenticationMethod[1];
            byte[] keyBytes = FileTools.GetBytes(privateKey);
            byte[] privateBytes = encoding.GetBytes(privateKey);
            var privateKeyFile = new PrivateKeyFile(new MemoryStream(privateBytes));
            var privateKeyAuthenticationMethod = new PrivateKeyAuthenticationMethod(user, privateKeyFile);
            auths[0] = privateKeyAuthenticationMethod;
            */
            //new PasswordAuthenticationMethod(username, ""),
            var connInfo = new ConnectionInfo(host, user, new AuthenticationMethod[]
            {
                new PrivateKeyAuthenticationMethod(user, new PrivateKeyFile[]
                       { new PrivateKeyFile(privateKeyLocation, "") }),
            });
            var sshClient = new SshClient(connInfo);
            try
            {
                sshClient.Connect();
                var cmd = sshClient.CreateCommand("ls -l");
                var res = cmd.Execute();
            }
            catch (Exception ex)
            {
                return false;
            }
            sshClient.Disconnect();
            return true;
        }
        public bool Connect(string host, string user, string password, int port)
        {
            var sshClient = new SshClient(host, port, user, password);
            try
            {
                sshClient.Connect();
                var cmd = sshClient.CreateCommand("ls -l");
                var res = cmd.Execute();
            }
            catch (Exception ex)
            {
                return false;
            }
            sshClient.Disconnect();
            return true;
        }
        public bool SendKey(string host, string user, string password, int port, string pub)
        {
            var sshClient = new SshClient(host, port, user, password);
            try
            {
                sshClient.Connect();
                var cmd = sshClient.CreateCommand($"echo \"{pub}\" >> ~/.ssh/authorized_keys");
                var asynch = cmd.BeginExecute();
                while (!asynch.IsCompleted)
                {
                    Thread.Sleep(1000);
                }
                var result = cmd.EndExecute(asynch);
                Console.Write(result);
                sshClient.Disconnect();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
            sshClient.Disconnect();
        }
        public bool SSHChangePassword(string host, string user, string password, int port, string newPassword)
        {
            var sshClient = new SshClient(host, port, user, password);
            try
            {
                sshClient.Connect();
                var cmd = sshClient.CreateCommand($"echo -e \"{newPassword}\n{newPassword}\" | passwd {user}");
                var asynch = cmd.BeginExecute();
                while (!asynch.IsCompleted)
                {
                    Thread.Sleep(1000);
                }
                var result = cmd.EndExecute(asynch);
                Console.Write(result);
                sshClient.Disconnect();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
            finally
            {
                sshClient.Disconnect();
            }
            
        }
        public bool SSHConnectTest(string host, string user, string password, int port)
        {
            var sshClient = new SshClient(host, port, user, password);
            try
            {
                sshClient.ConnectionInfo.Timeout = TimeSpan.FromSeconds(5);
                sshClient.Connect();
                return true;
            }
            catch (Exception ex)
            {
                //throw new Exception(string.Format("连接SFTP失败，原因：{0}", ex.Message));
                return false;
            }
            sshClient.Disconnect();
        }
        public void SSHExec(string host, string user, string password, int port,string finalCommand,Action<string> callback)
        {
            var sshClient = new SshClient(host, port, user, password);
            try
            {
                sshClient.Connect();
                var command = sshClient.CreateCommand(finalCommand);
                var result = command.BeginExecute();
                using (var reader =
                   new StreamReader(command.OutputStream, Encoding.UTF8, true, 1024, true))
                {
                    while (!result.IsCompleted || !reader.EndOfStream)
                    {
                        string line = reader.ReadLine();
                        if (line != null)
                        {
                            callback(line);
                        }
                    }
                }
                command.EndExecute(result);
            }
            catch (Exception ex)
            {
                //throw new Exception(string.Format("连接SFTP失败，原因：{0}", ex.Message));
                callback("fail");
            }
            finally
            {
                sshClient.Disconnect();
            }
        }
    }
}
